<!DOCTYPE html>
<html lang="en">

  <head>
    <meta charset="UTF-8" />
    <meta name="viewport"
          content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <style>
      body {
        background-color: white;
      }

      @keyframes ColorChange {
        0% {
          outline: 1px solid lightgreen;
        }

        50% {
          outline: 1px solid green;
        }

        1000% {
          outline: 1px solid lightgreen;
        }
      }

      svg {
        position: absolute;
        top: 50%;
        left: 50%;
        transform: translate3d(-50%, -50%, 0);
        outline: 1px solid red;
        animation: ColorChange 500ms ease infinite;
        transition: all linear 300;
      }

      line,
      polyline,
      rect {
        stroke-linecap: round;
        stroke-linejoin: round;
      }

      @keyframes starAnim {
        0% {
          fill-opacity: 1.0;
          stroke-width: 0;
        }

        20% {
          transform: translate(100px, 50px)
        }

        50% {
          transform: translate(100px, 50px) rotate(180deg)
        }

        80% {
          transform: translate(100px, 50px) rotate(360deg)
        }

        100% {
          fill-opacity: 0.0;
          stroke-width: 6;
        }
      }

      .starStyle {
        animation-name: starAnim;
        animation-duration: 3s;
        animation-iteration-count: infinite;
        animation-direction: alternate;
        animation-timing-function: ease;
        animation-play-state: running;
      }
    </style>
  </head>

  <body>
    <svg width="600"
         height="600"
         xmlns="http://www.w3.org/2000/svg"
         xmlns:xlink="http://www.w3.org/1999/xlink"
         preserveAspectRatio="xMinYMin meet"
         stroke-linecap="round"
         stroke-linejoin="round"
         viewBox="0 0 600 600">

      <!-- 第十二章 动画 -->


      <!-- 12.5 对复杂的属性应用动画 -->
      <polygon points="30 30 70 30 90 70 10 70"
               style="fill:#fcc; stroke:black">
        <animate id="animation"
                 attributeName="points"
                 attributeType="XML"
                 to="50 30 70 50 50 90 30 50"
                 begin="0s"
                 dur="2s"
                 fill="freeze"
                 repeatCount="indefinite" />
      </polygon>
      <path d="M15 50 Q 40 15, 50 50, 65 32, 100 40"
            style="fill:none; stroke: black"
            transform="translate(0,50)">
        <animate attributeName="d"
                 attributeType="XML"
                 to="M50 15 Q 15 40, 50 50, 32 65, 40 100"
                 begin="0s"
                 dur="3s"
                 fill="freeze"
                 repeatCount="indefinite" />
      </path>

      <!-- 12.6 指定多个值 -->
      <circle cx="150"
              cy="50"
              r="30"
              style="fill: #ff9; stroke:black;">
        <!--
          values：指定多个值
            想要首尾相接的动画，科室设置类似的形式：
              values="start; end; start;"
        -->
        <animate attributeName="fill"
                 begin="0s"
                 dur="1s"
                 values="#ff9;#99f;#f99;#9f9;#ff9;"
                 fill="freeze"
                 repeatCount="indefinite" />
      </circle>

      <!-- 12.7 多级动画时间 -->
      <!--
        animate的calcMode属性：
          paced：SVG 阅读器会计算后续各个值之间的间隔，并以此为依据划分持续时间，因此其变化的速度是恒定的（keyTimes 属性会被忽略）。适用于颜色、简单的数值或者长度，但不能用于点列表或者路径数据。
          linear：默认值，每个过度时恒定的
          discrete：动画会从一个值无过渡地跳到另一个之，类似css animation的step动画。
          spline：动画会按照keySplines属性加速或者减速，更多信息可以阅读SVG规范（http://www.w3.org/TR/SVG11/animate.html#KeySplinesAttribute）。
      -->

      <!--
        set元素：

      -->
      <circle cx="240"
              cy="40"
              r="30"
              style="fill: #ff9; stroke: gray;">
        <animate id="c1"
                 attributeName="r"
                 attributeType="XML"
                 begin="0s"
                 dur="4s"
                 from="30"
                 to="0"
                 fill="freeze" />
      </circle>
      <text text-anchor="middle"
            x="300"
            y="40"
            style="visibility: hidden;">
        <!-- 监听c1，动画end的时候把当前text的visibility属性设置为visible（可见）。 -->
        <set attributeName="visibility"
             attributeType="CSS"
             to="visible"
             begin="c1.end"
             dur="1s"
             fill="freeze" />
        They all gone!!
      </text>


      <!-- 12.9 animateTransform 元素 -->
      <g transform="translate(100,60)">
        <rect x="-10"
              y="-10"
              width="20"
              height="20"
              style="fill: #ff9; stroke: black;">
          <!-- 不生效，只能在xml的属性上生效，不能在css的transform上生效 -->
          <!-- <animate attributeName="transform"
                       begin="0s"
                       dur="4s"
                       from="1"
                       to="4 2"
                       fill="freeze" /> -->
          <animateTransform attributeType="XML"
                            attributeName="transform"
                            type="scale"
                            from="1"
                            to="4 2"
                            begin="0s"
                            dur="4s"
                            fill="freeze" />
        </rect>
      </g>

      <!-- 多个animateTransform动画需要设置additive属性 -->
      <rect x="-10"
            y="-10"
            width="20"
            height="20"
            style="fill: #ff9; stroke: black;">
        <animateTransform attributeName="transform"
                          attributeType="XML"
                          type="scale"
                          from="1"
                          to="4 2"
                          additive="sum"
                          begin="0s"
                          dur="4s"
                          fill="freeze" />
        <animateTransform attributeName="transform"
                          attributeType="XML"
                          type="rotate"
                          from="0"
                          to="45"
                          additive="sum"
                          begin="0s"
                          dur="4s"
                          fill="freeze" />
      </rect>

      <!-- 12.10 animateMotion元素（复杂路径动画） -->
      <defs>
        <g id="animateMotionEle">
          <!-- 要移动的三角形路径 -->
          <path d="M50,125 C 100,25 150,225, 200, 125"
                style="fill: none; stroke: blue;" />
          <!-- 三角形会沿着运动路径移动。路径原点与三角形底边中点垂直对齐 -->
          <path d="M-10,-3 L10,-3 L0,-25z"
                style="fill: yellow; stroke: red;">
            <animateMotion path="M50,125 C 100,25 150,225, 200, 125"
                           dur="6s"
                           fill="freeze" />
          </path>
        </g>

        <g id="motionRotate">
          <!-- 要移动的三角形路径 -->
          <path d="M50,125 C 100,25 150,225, 200, 125"
                style="fill: none; stroke: blue;" />
          <!-- 三角形会沿着运动路径移动。它通过在原点上方垂直方向上与三角形底边中心水平对齐的方式定义 -->
          <path d="M-10,-3 L10,-3 L0,-25z"
                style="fill: yellow; stroke: red;">
            <!-- rotate="auto"：自动根据路径旋转 -->
            <animateMotion path="M50,125 C 100,25 150,225, 200, 125"
                           rotate="auto"
                           dur="6s"
                           fill="freeze" />
          </path>
        </g>
        <g id="motionRotateHiddenPath">
          <path id="cubicCurve"
                d="M50,125 C 100,25 150,225, 200, 125"
                style="fill: none; stroke: blue;" />
          <path d="M-10,-3 L10,-3 L0,-25z"
                style="
                  fill: yellow;
                  stroke: red;
                  transform: rotateZ(90deg);
                ">
            <animateMotion dur="1s"
                           rotate="auto"
                           fill="freeze"
                           repeatCount="indefinite">
              <mpath xlink:href="#cubicCurve" />
            </animateMotion>
          </path>
        </g>

        <g id="pacedEle">
          <path d="M-10,-3 L10,-3 L0,-25z"
                style="fill: yellow; stroke: red;">
            <!--
              keyPoints：表示动画进度，取值0~1
              keyTimes：动画进度对应的时间进度，取值0~1
              可以控制动画的缓动，两者的值必须成对对应。
              并且必须设置 calcMode="linear"（或者 "spline"，但这不在本书讨论范围之内）。
            -->
            <animateMotion path="M50,125 C 100,25 150,225, 200, 125"
                           rotate="auto"
                           keyPoints="0;0.2;0.8;1"
                           keyTimes="0;0.33;0.66;1"
                           calcMode="linear"
                           dur="2s"
                           fill="freeze"
                           repeatCount="indefinite" />
          </path>
        </g>

        <!-- 使用css处理svg动画 -->
        <!-- 可能需要添加-webkit-前缀 -->
        <g id="starDef">
          <path d="M 38.042 -12.361 9.405 -12.944 -0.000 -40.000
            -9.405 -12.944 -38.042 -12.361 -15.217 4.944
            -23.511 32.361 0.000 16.000 23.511 32.361 15.217 4.944 Z" />
        </g>
      </defs>
      <use xlink:href="#animateMotionEle"
           x="350"
           y="0" />
      <use xlink:href="#motionRotate"
           x="0"
           y="100" />
      <use xlink:href="#motionRotateHiddenPath"
           x="200"
           y="100" />
      <use xlink:href="#pacedEle"
           x="400"
           y="100" />
      <use id="star"
           x="0"
           y="300"
           class="starStyle"
           xlink:href="#starDef"
           transform="translate(100, 100)"
           style="fill: #008000; stroke: #008000" />

    </svg>


    <script>
      const ele = document.querySelector("#xxx");
      let n = 0;
      function Renderer() {
        n++;
        if (n >= 360) n = 0;
        window.requestAnimationFrame(Renderer);
      }
      Renderer();
    </script>
  </body>

</html>
